package com.common.util.oss;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.UUID;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ObjectMetadata;
import com.common.util.DateUtil;

import net.coobird.thumbnailator.Thumbnails;

/**
 * 上传文件工具类
 * @author xiaohe
 *
 */
public class OSSAPIUtil {
	
	// 地区（这里是深圳的）
	private static String endpoint = "http://oss-cn-shenzhen.aliyuncs.com";
	// 阿里云id
	private static String accessKeyId = "LTAIovxUzFBILU3B";
	// 阿里云key
	private static String accessKeySecret = "iEjOPbAY9RshtrfCQZBpa0bVDvQptA";
	// 数据的容器（类似文件夹名）
	private static String bucketName = "chaoxiaozhu";
	// 路径（类似文件夹名）
	private static String realPath = "chaoxiaozhu";
	
	// 下载路径（类似文件夹名）
	private static String downLoadPath = "http://chaoxiaozhu.oss-cn-shenzhen.aliyuncs.com/";
	
	private static final Logger LOG = LoggerFactory.getLogger(OSSAPIUtil.class);
	
	/*
	 * 使用您的帐户构建一个客户端实例来访问OSS
	 */
	static OSSClient ossClient = new OSSClient(endpoint, accessKeyId,
			accessKeySecret);
	
	/**
	 * 上传多个文件
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public static List<String> uploadFiles(List<MultipartFile> file) throws IOException {
		List<String> list = new ArrayList<String>();
		for (MultipartFile f : file) {
			list.add(uploadFiles(f));
		}
		return list;
	}
	
	/**
	 * 上传文件
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public static String uploadFiles(MultipartFile file) throws IOException {
		String fileName = null;
		if(file == null){
			return null;
		}
		if (!file.isEmpty()) {
			String type = file.getContentType();
			String substring = type.substring(0, type.indexOf("/"));
			fileName = substring + "/" + getFileName(file);
			String str = saveFile(file.getInputStream(), fileName);
			if(str == null){
				return null;
			}
		}
		return fileName;
	}

	/**
	 * 重构文件名
	 * 
	 * @param fileName
	 * @return
	 * @throws IOException
	 */
	public static String getFileName(MultipartFile file) throws IOException {
		// 将文件生成MD5码
		String md5 = DigestUtils.md5Hex(IOUtils.toByteArray(file.getInputStream()));
		// 获取文件扩展名
		String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
		String fileName = md5 + "." + fileExt;
		return fileName;
	}

	/**
	 * 保存文件
	 * 
	 * @param file
	 * @return
	 */
	public static String saveFile(InputStream file, String fileName) {
		try {
			boolean exists = ossClient.doesObjectExist(bucketName, fileName);
			//文件是否存在 
			if (!exists) {
				PutObjectResult putObject = ossClient.putObject(new PutObjectRequest(bucketName, fileName, file));
				return putObject.getETag();
			}
			return "重复";
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 获得文件
	 * @param path
	 * @return
	 */
	public static String getFile(String path) {
		return downLoadPath+path;
	}
	
	/**
	 * 删除文件
	 * @param path
	 */
	public static void delteFile(String path){
		ossClient.deleteObject(bucketName, path);
	}
	
	/**
	 * 通用上传图片功能
	 * @param file 文件流
	 * @param role 上传资源所属角色 对应SysFilePathEnum
	 * @param type 长传资源所属类型 对应SysFilePathEnum
	 * @return
	 */

	public static String upload(MultipartFile file,String storagePath) {
		
		//验证上传文件是否为空
		if(file==null||file.isEmpty()){
			return null;
		}
		
		String filePath = upload(storagePath, file);
		
		return filePath;
	}
	
	/**
	 * <pre>
	 * 上传文件，返回文件访问路径
	 * storagePath示例：images/icons
	 * storagePath最后不要（切记）File.separator
	 * </pre>
	 *
	 * @param storagePath：存储的路径
	 * @param file：文件
	 * @return
	 */
	public static String upload(String storagePath, MultipartFile file) {
		String originFileName = file.getOriginalFilename();
		// 设置文件名
		String filePathName = (generateRelativeStoragePath(storagePath) + FileUtil.getExtension(originFileName))
				.replaceAll("\\\\", "/");
		// 设置校验md5
		MessageDigest messageDigest = null;
		byte[] fileContent = null;
		try {
			messageDigest = MessageDigest.getInstance("MD5");
			fileContent = file.getBytes();
		} catch (NoSuchAlgorithmException e) {
			LOG.error("Cannot get MD5 algorithm when preparing upload file to OSS.");
		} catch (IOException e) {
			LOG.error("Cannot get file content from {}.", originFileName);
		}
		messageDigest.update(fileContent);
		ObjectMetadata metadata = new ObjectMetadata();
		metadata.setContentLength(file.getSize());
		metadata.setHeader("Content-MD5", Base64Utils.encodeToString(messageDigest.digest()));
		// 存储
		try {
			/*InputStream inputStream = file.getInputStream();  
			// 把图片读入到内存中  
			BufferedImage bufImg = ImageIO.read(inputStream);  
			// 压缩代码  
			// 存储图片文件byte数组  
			ByteArrayOutputStream bos = new ByteArrayOutputStream();  
			//防止图片变红  
			 
			bufImg = Thumbnails.of(bufImg).scale(1f).outputQuality(0.25f).asBufferedImage();
			//先转成jpg格式来压缩,然后在通过OSS来修改成源文件本来的后缀格式  
			ImageIO.write(bufImg,"jpg",bos);  
			//获取输出流  
			inputStream = new ByteArrayInputStream(bos.toByteArray());  
			ObjectMetadata objectMeta = new ObjectMetadata();
		    objectMeta.setContentType("image/*");
		    objectMeta.setContentLength(inputStream.available());*/
			ossClient.putObject(bucketName, filePathName.replace("//", "/"), file.getInputStream(),metadata);
		} catch (OSSException | ClientException | IOException e) {
			LOG.error("OSS storage error", e);
		}

		return downLoadPath + filePathName;
	}
	

	/**
	 * <pre>
	 * 获取存储的相对路径
	 * 规则path + FileUtil.getFileSeparator() + yyyyMMddHH + FileUtil.getFileSeparator() + uuid
	 * </pre>
	 *
	 * @param storagePath
	 * @return
	 */
	public static String generateRelativeStoragePath(String storagePath) {
		String time = DateUtil.formatDateToString(new Date(), "yyyyMMddHH");
		StringBuilder sb = new StringBuilder(realPath).append(getFileSeparator());
		if (!StringUtils.isEmpty(storagePath)) {
			sb.append(storagePath).append(getFileSeparator());
		}
		sb.append(time).append(getFileSeparator()).append(UUID.randomUUID().toString());
		return sb.toString();
	}
	
	private static String getFileSeparator() {
		return FileUtil.getFileSeparator();
	}
	
}
